<!DOCTYPE html>
<html lang="en">
<head>
        <meta charset="utf-8" />
        <title>Part.3.B.2.classes-2</title>
        <link rel="stylesheet" href="/theme/css/main.css" />

        <!--[if IE]>
            <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
        <![endif]-->
</head>

<body id="index" class="home">
        <header id="banner" class="body">
                <h1><a href="/">PythonTutorials </a></h1>
                <nav><ul>
                    <li><a href="/category/cpp.html">cpp</a></li>
                    <li class="active"><a href="/category/python.html">python</a></li>
                </ul>
                </nav>
        </header><!-- /#banner -->
<section id="content" class="body">
  <article>
    <header>
      <h1 class="entry-title">
        <a href="/Part.3.B.2.classes-2.html" rel="bookmark"
           title="Permalink to Part.3.B.2.classes-2">Part.3.B.2.classes-2</a></h1>
    </header>

    <div class="entry-content">
<footer class="post-info">
        <span>Mon 06 April 2020</span>
<span>| tags: <a href="/tag/python.html">python</a><a href="/tag/progarmming.html">progarmming</a><a href="/tag/excel.html">Excel</a></span>
</footer><!-- /.post-info -->      <h1>类 —— Python 的实现</h1>
<p>既然已经在不碰代码的情况下，把 OOP 中的主要概念梳理清楚了，以下的行文中，那些概念就直接用英文罢，省得理解上还得再绕个弯……</p>
<h2>Defining Class</h2>
<p>Class 使用 <code>class</code> 关键字进行定义。</p>
<p>与函数定义不同的地方在于，Class 接收参数不是在 <code>class Classname():</code> 的括号里完成 —— 那个圆括号有另外的用处。</p>
<p>让我们先看看代码，而后再逐一解释：</p>
<div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">IPython.core.interactiveshell</span> <span class="kn">import</span> <span class="n">InteractiveShell</span>
<span class="n">InteractiveShell</span><span class="o">.</span><span class="n">ast_node_interactivity</span> <span class="o">=</span> <span class="s2">&quot;all&quot;</span>
<span class="kn">import</span> <span class="nn">datetime</span>

<span class="k">class</span> <span class="nc">Golem</span><span class="p">:</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">built_year</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">date</span><span class="o">.</span><span class="n">today</span><span class="p">()</span><span class="o">.</span><span class="n">year</span>

    <span class="k">def</span> <span class="nf">say_hi</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">print</span><span class="p">(</span><span class="s1">&#39;Hi!&#39;</span><span class="p">)</span>

<span class="n">g</span> <span class="o">=</span> <span class="n">Golem</span><span class="p">(</span><span class="s1">&#39;Clay&#39;</span><span class="p">)</span>
<span class="n">g</span><span class="o">.</span><span class="n">name</span>
<span class="n">g</span><span class="o">.</span><span class="n">built_year</span>
<span class="n">g</span><span class="o">.</span><span class="n">say_hi</span>
<span class="n">g</span><span class="o">.</span><span class="n">say_hi</span><span class="p">()</span>
<span class="nb">type</span><span class="p">(</span><span class="n">g</span><span class="p">)</span>
<span class="nb">type</span><span class="p">(</span><span class="n">g</span><span class="o">.</span><span class="n">name</span><span class="p">)</span>
<span class="nb">type</span><span class="p">(</span><span class="n">g</span><span class="o">.</span><span class="n">built_year</span><span class="p">)</span>
<span class="nb">type</span><span class="p">(</span><span class="n">g</span><span class="o">.</span><span class="fm">__init__</span><span class="p">)</span>
<span class="nb">type</span><span class="p">(</span><span class="n">g</span><span class="o">.</span><span class="n">say_hi</span><span class="p">)</span>
</pre></div>


<div class="highlight"><pre><span></span>&#39;Clay&#39;
2019
&lt;bound method Golem.say_hi of &lt;__main__.Golem object at 0x10430e7b8&gt;&gt;
Hi!
__main__.Golem
str
int
method
method
</pre></div>


<p>以上，我们创建了一个 Class:</p>
<div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Golem</span><span class="p">:</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">built_year</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">date</span><span class="o">.</span><span class="n">today</span><span class="p">()</span><span class="o">.</span><span class="n">year</span>
</pre></div>


<p>其中定义了当我们根据这个 Class 创建一个实例的时候，那个 Object 的初始化过程，即 <code>__init__()</code> 函数 —— 又由于这个函数是在 Class 中定义的，我们称它为 Class 的一个 Method。</p>
<p>这里的 <code>self</code> 就是个变量，跟程序中其它变量的区别在于，它是一个系统默认可以识别的变量，用来指代将来用这个 Class 创建的 Instance。</p>
<p>比如，我们创建了 Golem 这个 Class 的一个 Instance，<code>g = Golem('Clay')</code> 之后，我们写 <code>g.name</code>，那么解析器就去找 <code>g</code> 这个实例所在的 Scope 里有没有 <code>self.name</code>……</p>
<p>注意：<code>self</code> 这个变量的定义，是在 <code>def __init__(self, ...)</code> 这一句里完成的。对于这个变量的名称取名没有强制要求，你实际上可以随便用什么名字，很多 C 程序员会习惯于将这个变量命名为 <code>this</code> —— 但根据惯例，你最好还是只用 <code>self</code> 这个变量名，省得给别人造成误会。</p>
<p>在 Class 的代码中，如果定义了 <code>__init__()</code> 函数，那么系统就会将它当作 Instance 在创建后被初始化的函数。这个函数名称是强制指定的，初始化函数必须使用这个名称；注意 <code>init</code> 两端各有两个下划线 <code>_</code>。</p>
<p>当我们用 <code>g = Golem('Clay')</code> 这一句创建了一个 Golem 的 Instance 的时候，以下一连串的事情发生了：</p>
<blockquote>
<ul>
<li><code>g</code> 从此之后就是一个根据 Golem 这个 Class 创建的 Instance，对使用者来说，它就是个 Object；</li>
<li>因为 Golem 这个 Class 的代码中有 <code>__init__()</code>，所以，当 <code>g</code> 被创建的时候，<code>g</code> 就需要被初始化……</li>
<li>在 <code>g</code> 所在的变量目录中，出现了一个叫做 <code>self</code> 的用来指代 <code>g</code> 本身的变量；</li>
<li>self.name 接收了一个参数，<code>'Clay'</code>，并将其保存了下来；</li>
<li>生成了一个叫做 <code>self.built_year</code> 的变量，其中保存的是 <code>g</code> 这个 Object 被创建时的年份……</li>
</ul>
</blockquote>
<p>对了，Golem 和 Robot 一样，都是机器人的意思；Golem 的本义来自于犹太神话，一个被赋予了生命的泥人……</p>
<h2>Inheritance</h2>
<p>我们刚刚创建了一个 Golem Class，如果我们想用它 Inherite 一个新的 Class，比如，<code>Running_Golem</code>，一个能跑的机器人，那就像以下的代码那样做 —— 注意 <code>class Running_Golem</code> 之后的圆括号：</p>
<div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">IPython.core.interactiveshell</span> <span class="kn">import</span> <span class="n">InteractiveShell</span>
<span class="n">InteractiveShell</span><span class="o">.</span><span class="n">ast_node_interactivity</span> <span class="o">=</span> <span class="s2">&quot;all&quot;</span>
<span class="kn">import</span> <span class="nn">datetime</span>

<span class="k">class</span> <span class="nc">Golem</span><span class="p">:</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">built_year</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">date</span><span class="o">.</span><span class="n">today</span><span class="p">()</span><span class="o">.</span><span class="n">year</span>

    <span class="k">def</span> <span class="nf">say_hi</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">print</span><span class="p">(</span><span class="s1">&#39;Hi!&#39;</span><span class="p">)</span>

<span class="k">class</span> <span class="nc">Running_Golem</span><span class="p">(</span><span class="n">Golem</span><span class="p">):</span>      <span class="c1"># 刚刚就说，这个圆括号另有用途……</span>

    <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">print</span><span class="p">(</span><span class="s2">&quot;Can&#39;t you see? I&#39;m running...&quot;</span><span class="p">)</span>

<span class="n">rg</span> <span class="o">=</span> <span class="n">Running_Golem</span><span class="p">(</span><span class="s1">&#39;Clay&#39;</span><span class="p">)</span>

<span class="n">rg</span><span class="o">.</span><span class="n">run</span>
<span class="n">rg</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
<span class="n">rg</span><span class="o">.</span><span class="n">name</span>
<span class="n">rg</span><span class="o">.</span><span class="n">built_year</span>
<span class="n">rg</span><span class="o">.</span><span class="n">say_hi</span><span class="p">()</span>
</pre></div>


<div class="highlight"><pre><span></span>&lt;bound method Running_Golem.run of &lt;__main__.Running_Golem object at 0x1068b37b8&gt;&gt;
Can&#39;t you see? I&#39;m running...
&#39;Clay&#39;
2019
Hi!
</pre></div>


<p>如此这般，我们根据 Golem 这个 Class 创造了一个 Subclass —— <code>Running_Golem</code>，既然它是 Golem 的 Inheritance，那么 Golem 有的 Attributes 和 Methods 它都有，并且还多了一个 Method —— <code>self.run</code>。</p>
<h2>Overrides</h2>
<p>当我们创建一个 Inherited Class 的时候，可以重写（Overriding）Parent Class 中的 Methods。比如这样：</p>
<div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">IPython.core.interactiveshell</span> <span class="kn">import</span> <span class="n">InteractiveShell</span>
<span class="n">InteractiveShell</span><span class="o">.</span><span class="n">ast_node_interactivity</span> <span class="o">=</span> <span class="s2">&quot;all&quot;</span>
<span class="kn">import</span> <span class="nn">datetime</span>

<span class="k">class</span> <span class="nc">Golem</span><span class="p">:</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">built_year</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">date</span><span class="o">.</span><span class="n">today</span><span class="p">()</span><span class="o">.</span><span class="n">year</span>

    <span class="k">def</span> <span class="nf">say_hi</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">print</span><span class="p">(</span><span class="s1">&#39;Hi!&#39;</span><span class="p">)</span>

<span class="k">class</span> <span class="nc">runningGolem</span><span class="p">(</span><span class="n">Golem</span><span class="p">):</span>

    <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">print</span><span class="p">(</span><span class="s2">&quot;Can&#39;t you see? I&#39;m running...&quot;</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">say_hi</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>                            <span class="c1"># 不再使用 Parent Class 中的定义，而是新的……</span>
        <span class="k">print</span><span class="p">(</span><span class="s1">&#39;Hey! Nice day, Huh?&#39;</span><span class="p">)</span>

<span class="n">rg</span> <span class="o">=</span> <span class="n">runningGolem</span><span class="p">(</span><span class="s1">&#39;Clay&#39;</span><span class="p">)</span>
<span class="n">rg</span><span class="o">.</span><span class="n">run</span>
<span class="n">rg</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
<span class="n">rg</span><span class="o">.</span><span class="n">name</span>
<span class="n">rg</span><span class="o">.</span><span class="n">built_year</span>
<span class="n">rg</span><span class="o">.</span><span class="n">say_hi</span><span class="p">()</span>
</pre></div>


<div class="highlight"><pre><span></span>&lt;bound method runningGolem.run of &lt;__main__.runningGolem object at 0x1068c8128&gt;&gt;
Can&#39;t you see? I&#39;m running...
&#39;Clay&#39;
2019
Hey! Nice day, Huh?
</pre></div>


<h2>Inspecting A Class</h2>
<p>当我们作为用户想了解一个 Class 的 Interface，即，它的 Attributes 和 Methods 的时候，常用的有三种方式：</p>
<div class="highlight"><pre><span></span><span class="mf">1.</span> <span class="n">help</span><span class="p">(</span><span class="nb">object</span><span class="p">)</span>
<span class="mf">2.</span> <span class="nb">dir</span><span class="p">(</span><span class="nb">object</span><span class="p">)</span>
<span class="mf">3.</span> <span class="nb">object</span><span class="o">.</span><span class="vm">__dict__</span>
</pre></div>


<div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">IPython.core.interactiveshell</span> <span class="kn">import</span> <span class="n">InteractiveShell</span>
<span class="n">InteractiveShell</span><span class="o">.</span><span class="n">ast_node_interactivity</span> <span class="o">=</span> <span class="s2">&quot;all&quot;</span>
<span class="kn">import</span> <span class="nn">datetime</span>

<span class="k">class</span> <span class="nc">Golem</span><span class="p">:</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">built_year</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">date</span><span class="o">.</span><span class="n">today</span><span class="p">()</span><span class="o">.</span><span class="n">year</span>

    <span class="k">def</span> <span class="nf">say_hi</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">print</span><span class="p">(</span><span class="s1">&#39;Hi!&#39;</span><span class="p">)</span>

<span class="k">class</span> <span class="nc">runningGolem</span><span class="p">(</span><span class="n">Golem</span><span class="p">):</span>

    <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">print</span><span class="p">(</span><span class="s1">&#39;Can</span><span class="se">\&#39;</span><span class="s1">t you see? I</span><span class="se">\&#39;</span><span class="s1">m running...&#39;</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">say_hi</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>                            <span class="c1"># 不再使用 Parent Class 中的定义，而是新的……</span>
        <span class="k">print</span><span class="p">(</span><span class="s1">&#39;Hey! Nice day, Huh?&#39;</span><span class="p">)</span>

<span class="n">rg</span> <span class="o">=</span> <span class="n">runningGolem</span><span class="p">(</span><span class="s1">&#39;Clay&#39;</span><span class="p">)</span>
<span class="n">help</span><span class="p">(</span><span class="n">rg</span><span class="p">)</span>
<span class="nb">dir</span><span class="p">(</span><span class="n">rg</span><span class="p">)</span>
<span class="n">rg</span><span class="o">.</span><span class="vm">__dict__</span>
<span class="nb">hasattr</span><span class="p">(</span><span class="n">rg</span><span class="p">,</span> <span class="s1">&#39;built_year&#39;</span><span class="p">)</span>
</pre></div>


<div class="highlight"><pre><span></span><span class="nx">Help</span> <span class="nx">on</span> <span class="nx">runningGolem</span> <span class="k">in</span> <span class="kr">module</span> <span class="nx">__main__</span> <span class="nx">object</span>:

<span class="kt">class</span> <span class="nx">runningGolem</span><span class="p">(</span><span class="nx">Golem</span><span class="p">)</span>
 <span class="o">|</span>  <span class="nx">runningGolem</span><span class="p">(</span><span class="nx">name</span><span class="o">=</span><span class="nx">None</span><span class="p">)</span>
 <span class="o">|</span>
 <span class="o">|</span>  <span class="nx">Method</span> <span class="nx">resolution</span> <span class="nx">order</span><span class="o">:</span>
 <span class="o">|</span>      <span class="nx">runningGolem</span>
 <span class="o">|</span>      <span class="nx">Golem</span>
 <span class="o">|</span>      <span class="nx">builtins</span><span class="p">.</span><span class="nx">object</span>
 <span class="o">|</span>
 <span class="o">|</span>  <span class="nx">Methods</span> <span class="nx">defined</span> <span class="nx">here</span><span class="o">:</span>
 <span class="o">|</span>
 <span class="o">|</span>  <span class="nx">run</span><span class="p">(</span><span class="nx">self</span><span class="p">)</span>
 <span class="o">|</span>
 <span class="o">|</span>  <span class="nx">say_hi</span><span class="p">(</span><span class="nx">self</span><span class="p">)</span>
 <span class="o">|</span>
 <span class="o">|</span>  <span class="o">----------------------------------------------------------------------</span>
 <span class="o">|</span>  <span class="nx">Methods</span> <span class="nx">inherited</span> <span class="nx">from</span> <span class="nx">Golem</span><span class="o">:</span>
 <span class="o">|</span>
 <span class="o">|</span>  <span class="nx">__init__</span><span class="p">(</span><span class="nx">self</span><span class="p">,</span> <span class="nx">name</span><span class="o">=</span><span class="nx">None</span><span class="p">)</span>
 <span class="o">|</span>      <span class="nx">Initialize</span> <span class="nx">self</span><span class="p">.</span>  <span class="nx">See</span> <span class="nx">help</span><span class="p">(</span><span class="nx">type</span><span class="p">(</span><span class="nx">self</span><span class="p">))</span> <span class="k">for</span> <span class="nx">accurate</span> <span class="nx">signature</span><span class="p">.</span>
 <span class="o">|</span>
 <span class="o">|</span>  <span class="o">----------------------------------------------------------------------</span>
 <span class="o">|</span>  <span class="nx">Data</span> <span class="nx">descriptors</span> <span class="nx">inherited</span> <span class="nx">from</span> <span class="nx">Golem</span><span class="o">:</span>
 <span class="o">|</span>
 <span class="o">|</span>  <span class="nx">__dict__</span>
 <span class="o">|</span>      <span class="nx">dictionary</span> <span class="k">for</span> <span class="nx">instance</span> <span class="nx">variables</span> <span class="p">(</span><span class="k">if</span> <span class="nx">defined</span><span class="p">)</span>
 <span class="o">|</span>
 <span class="o">|</span>  <span class="nx">__weakref__</span>
 <span class="o">|</span>      <span class="nx">list</span> <span class="nx">of</span> <span class="nx">weak</span> <span class="nx">references</span> <span class="nx">to</span> <span class="nx">the</span> <span class="nx">object</span> <span class="p">(</span><span class="k">if</span> <span class="nx">defined</span><span class="p">)</span>

<span class="p">[</span><span class="s1">&#39;__class__&#39;</span><span class="p">,</span>
 <span class="s1">&#39;__delattr__&#39;</span><span class="p">,</span>
 <span class="s1">&#39;__dict__&#39;</span><span class="p">,</span>
 <span class="s1">&#39;__dir__&#39;</span><span class="p">,</span>
 <span class="s1">&#39;__doc__&#39;</span><span class="p">,</span>
 <span class="s1">&#39;__eq__&#39;</span><span class="p">,</span>
 <span class="s1">&#39;__format__&#39;</span><span class="p">,</span>
 <span class="s1">&#39;__ge__&#39;</span><span class="p">,</span>
 <span class="s1">&#39;__getattribute__&#39;</span><span class="p">,</span>
 <span class="s1">&#39;__gt__&#39;</span><span class="p">,</span>
 <span class="s1">&#39;__hash__&#39;</span><span class="p">,</span>
 <span class="s1">&#39;__init__&#39;</span><span class="p">,</span>
 <span class="s1">&#39;__init_subclass__&#39;</span><span class="p">,</span>
 <span class="s1">&#39;__le__&#39;</span><span class="p">,</span>
 <span class="s1">&#39;__lt__&#39;</span><span class="p">,</span>
 <span class="s1">&#39;__module__&#39;</span><span class="p">,</span>
 <span class="s1">&#39;__ne__&#39;</span><span class="p">,</span>
 <span class="s1">&#39;__new__&#39;</span><span class="p">,</span>
 <span class="s1">&#39;__reduce__&#39;</span><span class="p">,</span>
 <span class="s1">&#39;__reduce_ex__&#39;</span><span class="p">,</span>
 <span class="s1">&#39;__repr__&#39;</span><span class="p">,</span>
 <span class="s1">&#39;__setattr__&#39;</span><span class="p">,</span>
 <span class="s1">&#39;__sizeof__&#39;</span><span class="p">,</span>
 <span class="s1">&#39;__str__&#39;</span><span class="p">,</span>
 <span class="s1">&#39;__subclasshook__&#39;</span><span class="p">,</span>
 <span class="s1">&#39;__weakref__&#39;</span><span class="p">,</span>
 <span class="s1">&#39;built_year&#39;</span><span class="p">,</span>
 <span class="s1">&#39;name&#39;</span><span class="p">,</span>
 <span class="s1">&#39;run&#39;</span><span class="p">,</span>
 <span class="s1">&#39;say_hi&#39;</span><span class="p">]</span>
<span class="p">{</span><span class="s1">&#39;name&#39;</span><span class="o">:</span> <span class="s1">&#39;Clay&#39;</span><span class="p">,</span> <span class="s1">&#39;built_year&#39;</span><span class="o">:</span> <span class="mi">2019</span><span class="p">}</span>
<span class="nx">True</span>
</pre></div>


<h2>Scope</h2>
<p>每个变量都属于某一个 <strong>Scope</strong>（变量的作用域），在同一个 Scope 中，变量可以被引用被操作…… 这么说非常抽象，难以理解 —— 只能通过例子说明。</p>
<p>我们先给 Golem 这个 Class 增加一点功能 —— 我们需要随时知道究竟有多少个 Golem 处于活跃状态…… 也因此顺带给 Golem 加上一个 Method：<code>cease()</code> —— 哈！机器人么，想关掉它，说关掉它，就能关掉它；</p>
<p>另外，我们还要给机器人设置个使用年限，比如 10 年；</p>
<p>…… 而外部会每隔一段时间，用 <code>Golem.is_active()</code> 去检查所有的机器人，所以，不需要外部额外操作，到了年头，它应该能关掉自己。—— 当然，又由于以下代码是简化书写的，核心目的是为了讲解 Scope，所以并没有专门写模拟 10 年后某些机器人自动关闭的情形……</p>
<p>在运行以下代码之前，需要先介绍三个 Python 的内建函数：</p>
<blockquote>
<ul>
<li><code>hasattr(object, attr)</code> 查询这个 <code>object</code> 中有没有这个 <code>attr</code>，返回布尔值</li>
<li><code>getattr(object, attr)</code> 获取这个 <code>object</code> 中这个 <code>attr</code> 的值</li>
<li><code>setattr(object, attr, value)</code> 将这个 <code>object</code> 中的 <code>attr</code> 值设置为 <code>value</code></li>
</ul>
</blockquote>
<p>现在的你，应该一眼望过去，就已经能掌握这三个内建函数的用法 —— 还记得之前的你吗？眼睁睁看着，那些字母放在那里对你来说没任何意义…… 这才多久啊！</p>
<div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">IPython.core.interactiveshell</span> <span class="kn">import</span> <span class="n">InteractiveShell</span>
<span class="n">InteractiveShell</span><span class="o">.</span><span class="n">ast_node_interactivity</span> <span class="o">=</span> <span class="s2">&quot;all&quot;</span>
<span class="kn">import</span> <span class="nn">datetime</span>

<span class="k">class</span> <span class="nc">Golem</span><span class="p">:</span>
    <span class="n">population</span> <span class="o">=</span> <span class="mi">0</span>
    <span class="n">__life_span</span> <span class="o">=</span> <span class="mi">10</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">built_year</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">date</span><span class="o">.</span><span class="n">today</span><span class="p">()</span><span class="o">.</span><span class="n">year</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">__active</span> <span class="o">=</span> <span class="bp">True</span>
        <span class="n">Golem</span><span class="o">.</span><span class="n">population</span> <span class="o">+=</span> <span class="mi">1</span>          <span class="c1"># 执行一遍之后，试试把这句改成 population += 1</span>

    <span class="k">def</span> <span class="nf">say_hi</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">print</span><span class="p">(</span><span class="s1">&#39;Hi!&#39;</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">cease</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">__active</span> <span class="o">=</span> <span class="bp">False</span>
        <span class="n">Golem</span><span class="o">.</span><span class="n">population</span> <span class="o">-=</span> <span class="mi">1</span>

    <span class="k">def</span> <span class="nf">is_active</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">datetime</span><span class="o">.</span><span class="n">date</span><span class="o">.</span><span class="n">today</span><span class="p">()</span><span class="o">.</span><span class="n">year</span> <span class="o">-</span> <span class="bp">self</span><span class="o">.</span><span class="n">built_year</span> <span class="o">&gt;=</span> <span class="n">Golem</span><span class="o">.</span><span class="n">__life_span</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">cease</span><span class="p">()</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">__active</span>

<span class="n">g</span> <span class="o">=</span> <span class="n">Golem</span><span class="p">()</span>
<span class="nb">hasattr</span><span class="p">(</span><span class="n">Golem</span><span class="p">,</span> <span class="s1">&#39;population&#39;</span><span class="p">)</span>      <span class="c1"># True</span>
<span class="nb">hasattr</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="s1">&#39;population&#39;</span><span class="p">)</span>          <span class="c1"># True</span>
<span class="nb">hasattr</span><span class="p">(</span><span class="n">Golem</span><span class="p">,</span> <span class="s1">&#39;__life_span&#39;</span><span class="p">)</span>     <span class="c1"># False</span>
<span class="nb">hasattr</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="s1">&#39;__life_span&#39;</span><span class="p">)</span>         <span class="c1"># False</span>
<span class="nb">hasattr</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="s1">&#39;__active&#39;</span><span class="p">)</span>            <span class="c1"># False</span>
<span class="n">Golem</span><span class="o">.</span><span class="n">population</span>                  <span class="c1"># 1</span>
<span class="nb">setattr</span><span class="p">(</span><span class="n">Golem</span><span class="p">,</span> <span class="s1">&#39;population&#39;</span><span class="p">,</span> <span class="mi">10</span><span class="p">)</span>
<span class="n">Golem</span><span class="o">.</span><span class="n">population</span>                  <span class="c1"># 10</span>
<span class="n">x</span> <span class="o">=</span> <span class="n">Golem</span><span class="p">()</span>
<span class="n">Golem</span><span class="o">.</span><span class="n">population</span>                  <span class="c1"># 11</span>
<span class="n">x</span><span class="o">.</span><span class="n">cease</span><span class="p">()</span>
<span class="n">Golem</span><span class="o">.</span><span class="n">population</span>                  <span class="c1"># 10</span>
<span class="nb">getattr</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="s1">&#39;population&#39;</span><span class="p">)</span>          <span class="c1"># 10</span>
<span class="n">g</span><span class="o">.</span><span class="n">is_active</span><span class="p">()</span>
</pre></div>


<div class="highlight"><pre><span></span>True
True
False
False
False
1
10
11
10
10
True
</pre></div>


<p>如果你试过把第 13 行的 <code>Golem.population += 1</code> 改成 <code>population += 1</code>，你会被如下信息提醒：</p>
<div class="highlight"><pre><span></span>     <span class="mi">12</span>         <span class="bp">self</span><span class="o">.</span><span class="n">__active</span> <span class="o">=</span> <span class="bp">True</span>
<span class="o">---&gt;</span> <span class="mi">13</span>         <span class="n">population</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="ne">UnboundLocalError</span><span class="p">:</span> <span class="n">local</span> <span class="n">variable</span> <span class="s1">&#39;population&#39;</span> <span class="n">referenced</span> <span class="n">before</span> <span class="n">assignment</span>
</pre></div>


<p>—— 本地变量 <code>population</code> 尚未赋值，就已经提前被引用…… 为什么会这样呢？因为在你所创建 <code>g</code> 之后，马上执行的是 <code>__init()__</code> 这个初始化函数，而 <code>population</code> 是在这个函数之外定义的……</p>
<p>如果你足够细心，你会发现这个版本中，有些变量前面有两个下划线 <code>__</code>，比如，<code>__life_span</code> 和 <code>self.__active</code>。这是 Python 的定义，变量名前面加上一个以上下划线（Underscore）<code>_</code> 的话，那么该变量是 “私有变量”（Private Variables），不能被外部引用。而按照 Python 的惯例，我们会使用两个下划线起始，去命名私有变量，如：<code>__life_span</code>。你可以回去试试，把所有的 <code>__life_span</code> 改成 <code>_life_span</code>（即，变量名开头只有一个 <code>_</code>，那么，<code>hasattr(Golem, '_life_span')</code> 和 <code>hasattr(g, '_life_span')</code> 的返回值就都变成了 <code>True</code>。</p>
<p>看看下面的图示，理解起来更为直观一些，其中每个方框代表一个 Scope：</p>
<p><img alt="123" src="https://raw.githubusercontent.com/selfteaching/the-craft-of-selfteaching/master/images/class-variables-scope.png?raw=true"></p>
<p>整个代码启动之后，总计有 4 个 Scopes 如图所示：</p>
<blockquote>
<ul>
<li>① <code>class Golem</code> 之外；</li>
<li>② <code>class Golem</code> 之内；</li>
<li>③ <code>__init__(self, name=None)</code> 之内；</li>
<li>④ <code>cease(self)</code> 之内；</li>
</ul>
</blockquote>
<p>在 Scope ① 中，可以引用 <code>Golem.population</code>，在生成一个 Golem 的实例 <code>g</code> 之后，也可以引用 <code>g.population</code>；但 <code>Golem.__life_span</code> 和 <code>g.__active</code> 在 Scope ① 是不存在的；</p>
<p>在 Scope ② 中，存在两个变量，<code>population</code> 和 <code>__life_span</code>；而 <code>__life_span</code> 是 Private（私有变量，因为它的变量名中前两个字符是下划线 <code>__</code>；于是，在 Scope ① 中，不存在 <code>Golem.__life_span</code> —— <code>hasattr(Golem, '__life_span')</code> 的值为 <code>False</code>；</p>
<p>在 Scope ③ 中和 Scope ④ 中，由于都给它们传递了 <code>self</code> 这个参数，于是，在这两个 Scope 里，都可以引用 <code>self.xxx</code>，比如 <code>self.population</code>，比如 <code>self.__life_span</code>；</p>
<p>在 Scope ③ 中，<code>population</code> 是不存在的，如果需要引用这个值，可以用 <code>Golem.population</code>，也可以用 <code>self.population</code>。同样的道理，在 Scope ③ 中 <code>__life_span</code> 也不存在，如果想用这个值，可以用 <code>Golem.__life_span</code> 或者 <code>self.__life_span</code>；</p>
<p>Scope ④ 与 Scope ③ 平行存在。所以在这里，<code>population</code> 和 <code>__life_span</code> 也同样并不存在。</p>
<p><strong>补充</strong></p>
<p>在本例子中，在 <code>__init__(self, name=None)</code> 函数中 <code>self.population</code> 和 <code>Golem.population</code> 都可以使用，但使用效果是不一样的：</p>
<blockquote>
<ul>
<li><code>self.population</code> 总是去读取 <code>Golem</code> 类中 <code>population</code> 的初始值，即使后面通过 <code>setattr(Golem, 'population', 10)</code> 更改 <code>population</code> 的值后，<code>self.population</code> 的值仍为 <code>0</code>，但 <code>Golem.population</code> 值则为 <code>10</code>，你可以自己动手尝试一下。</li>
</ul>
</blockquote>
<h2>Encapsulation</h2>
<p>到目前为止，Golem 这个 Class 看起来不错，但有个问题，它里面的数据，外面是可以随便改的 —— 虽然，我们已经通过给变量 life_span 前面加上两个下划线，变成 <code>__life_span</code>，使其成为私有变量，外部不能触达（你不能引用 <code>Golem.__life_span</code>），可 Golem.population 就不一样，外面随时可以引用，还可以随时修改它，只需要写上一句：</p>
<div class="highlight"><pre><span></span><span class="n">Golem</span><span class="o">.</span><span class="n">population</span> <span class="o">=</span> <span class="mi">1000000</span>
</pre></div>


<p>我们干脆把 <code>population</code> 这个变量也改成私有的罢：<code>__population</code>，而后需要从外界查看这个变量的话，就在 Class 里面写个函数，返回那个值好了：</p>
<div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">IPython.core.interactiveshell</span> <span class="kn">import</span> <span class="n">InteractiveShell</span>
<span class="n">InteractiveShell</span><span class="o">.</span><span class="n">ast_node_interactivity</span> <span class="o">=</span> <span class="s2">&quot;all&quot;</span>
<span class="kn">import</span> <span class="nn">datetime</span>

<span class="k">class</span> <span class="nc">Golem</span><span class="p">:</span>
    <span class="n">__population</span> <span class="o">=</span> <span class="mi">0</span>
    <span class="n">__life_span</span> <span class="o">=</span> <span class="mi">10</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">built_year</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">date</span><span class="o">.</span><span class="n">today</span><span class="p">()</span><span class="o">.</span><span class="n">year</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">__active</span> <span class="o">=</span> <span class="bp">True</span>
        <span class="n">Golem</span><span class="o">.</span><span class="n">__population</span> <span class="o">+=</span> <span class="mi">1</span>

    <span class="k">def</span> <span class="nf">say_hi</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">print</span><span class="p">(</span><span class="s1">&#39;Hi!&#39;</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">cease</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">__active</span> <span class="o">=</span> <span class="bp">False</span>
        <span class="n">Golem</span><span class="o">.</span><span class="n">__population</span> <span class="o">-=</span> <span class="mi">1</span>

    <span class="k">def</span> <span class="nf">is_active</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">datetime</span><span class="o">.</span><span class="n">date</span><span class="o">.</span><span class="n">today</span><span class="p">()</span><span class="o">.</span><span class="n">year</span> <span class="o">-</span> <span class="bp">self</span><span class="o">.</span><span class="n">built_year</span> <span class="o">&gt;=</span> <span class="n">Golem</span><span class="o">.</span><span class="n">__life_span</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">cease</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">__active</span>

    <span class="k">def</span> <span class="nf">population</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">Golem</span><span class="o">.</span><span class="n">__population</span>

<span class="n">g</span> <span class="o">=</span> <span class="n">Golem</span><span class="p">(</span><span class="s1">&#39;Clay&#39;</span><span class="p">)</span>
<span class="n">g</span><span class="o">.</span><span class="n">population</span>
<span class="n">g</span><span class="o">.</span><span class="n">population</span><span class="p">()</span>
</pre></div>


<div class="highlight"><pre><span></span>&lt;bound method Golem.population of &lt;__main__.Golem object at 0x1068da160&gt;&gt;
1
</pre></div>


<p>如果，你希望外部能够像获得 Class 的属性那样，直接写 <code>g.population</code>，而不是必须加上一个括号 <code>g.population()</code> 传递参数（实际上传递了一个隐含的 <code>self</code> 参数），那么可以在 <code>def population(self):</code> 之前的一行加上一句 <code>@property</code>：</p>
<div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Golem</span><span class="p">:</span>
    <span class="n">__population</span> <span class="o">=</span> <span class="mi">0</span>
    <span class="o">...</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">population</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">Golem</span><span class="o">.</span><span class="n">__population</span>
</pre></div>


<p>如此这般之后，你就可以用 <code>g.population</code> 了：</p>
<div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">IPython.core.interactiveshell</span> <span class="kn">import</span> <span class="n">InteractiveShell</span>
<span class="n">InteractiveShell</span><span class="o">.</span><span class="n">ast_node_interactivity</span> <span class="o">=</span> <span class="s2">&quot;all&quot;</span>
<span class="kn">import</span> <span class="nn">datetime</span>

<span class="k">class</span> <span class="nc">Golem</span><span class="p">:</span>
    <span class="n">__population</span> <span class="o">=</span> <span class="mi">0</span>
    <span class="n">__life_span</span> <span class="o">=</span> <span class="mi">10</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">built_year</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">date</span><span class="o">.</span><span class="n">today</span><span class="p">()</span><span class="o">.</span><span class="n">year</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">__active</span> <span class="o">=</span> <span class="bp">True</span>
        <span class="n">Golem</span><span class="o">.</span><span class="n">__population</span> <span class="o">+=</span> <span class="mi">1</span>

    <span class="k">def</span> <span class="nf">say_hi</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">print</span><span class="p">(</span><span class="s1">&#39;Hi!&#39;</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">cease</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">__active</span> <span class="o">=</span> <span class="bp">False</span>
        <span class="n">Golem</span><span class="o">.</span><span class="n">__population</span> <span class="o">-=</span> <span class="mi">1</span>

    <span class="k">def</span> <span class="nf">is_active</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">datetime</span><span class="o">.</span><span class="n">date</span><span class="o">.</span><span class="n">today</span><span class="p">()</span><span class="o">.</span><span class="n">year</span> <span class="o">-</span> <span class="bp">self</span><span class="o">.</span><span class="n">built_year</span> <span class="o">&gt;=</span> <span class="n">Golem</span><span class="o">.</span><span class="n">__life_span</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">cease</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">__active</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">population</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">Golem</span><span class="o">.</span><span class="n">__population</span>

<span class="n">g</span> <span class="o">=</span> <span class="n">Golem</span><span class="p">(</span><span class="s1">&#39;Clay&#39;</span><span class="p">)</span>
<span class="n">g</span><span class="o">.</span><span class="n">population</span>
<span class="c1"># g.population = 100</span>
</pre></div>


<div class="highlight"><pre><span></span>1
</pre></div>


<p>如此这般之后，不仅你可以直接引用 <code>g.population</code>，并且，在外部不能再直接给 <code>g.population</code> 赋值了，否则会报错：</p>
<div class="highlight"><pre><span></span><span class="o">---------------------------------------------------------------------------</span>
<span class="ne">AttributeError</span>                            <span class="n">Traceback</span> <span class="p">(</span><span class="n">most</span> <span class="n">recent</span> <span class="n">call</span> <span class="n">last</span><span class="p">)</span>
<span class="o">&lt;</span><span class="n">ipython</span><span class="o">-</span><span class="nb">input</span><span class="o">-</span><span class="mi">16</span><span class="o">-</span><span class="mi">5</span><span class="n">d8c475304d3</span><span class="o">&gt;</span> <span class="ow">in</span> <span class="o">&lt;</span><span class="n">module</span><span class="o">&gt;</span>
     <span class="mi">26</span> <span class="n">g</span> <span class="o">=</span> <span class="n">Golem</span><span class="p">(</span><span class="s1">&#39;Clay&#39;</span><span class="p">)</span>
     <span class="mi">27</span> <span class="n">g</span><span class="o">.</span><span class="n">population</span>
<span class="o">---&gt;</span> <span class="mi">28</span> <span class="n">g</span><span class="o">.</span><span class="n">population</span> <span class="o">=</span> <span class="mi">100</span>

<span class="ne">AttributeError</span><span class="p">:</span> <span class="n">can</span><span class="s1">&#39;t set attribute</span>
</pre></div>


<p>到此为止，Encapsulation 就做得不错了。</p>
<p>如果你非得希望从外部可以设置这个值，那么，你就得再写个函数，并且在函数之前加上一句：</p>
<div class="highlight"><pre><span></span>    <span class="o">...</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">population</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">Golem</span><span class="o">.</span><span class="n">__population</span>

    <span class="nd">@population.setter</span>
    <span class="k">def</span> <span class="nf">population</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
        <span class="n">Golem</span><span class="o">.</span><span class="n">__population</span> <span class="o">=</span> <span class="n">value</span>
</pre></div>


<p>这样之后，<code>.population</code> 这个 Attribute 就可以从外部被设定其值了（虽然在当前的例子中显得没必要让外部设定 <code>__population</code> 这个值…… 以下仅仅是为了举例）：</p>
<div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">IPython.core.interactiveshell</span> <span class="kn">import</span> <span class="n">InteractiveShell</span>
<span class="n">InteractiveShell</span><span class="o">.</span><span class="n">ast_node_interactivity</span> <span class="o">=</span> <span class="s2">&quot;all&quot;</span>
<span class="kn">import</span> <span class="nn">datetime</span>

<span class="k">class</span> <span class="nc">Golem</span><span class="p">:</span>
    <span class="n">__population</span> <span class="o">=</span> <span class="mi">0</span>
    <span class="n">__life_span</span> <span class="o">=</span> <span class="mi">10</span>

    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">built_year</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">date</span><span class="o">.</span><span class="n">today</span><span class="p">()</span><span class="o">.</span><span class="n">year</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">__active</span> <span class="o">=</span> <span class="bp">True</span>
        <span class="n">Golem</span><span class="o">.</span><span class="n">__population</span> <span class="o">+=</span> <span class="mi">1</span>

    <span class="k">def</span> <span class="nf">say_hi</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">print</span><span class="p">(</span><span class="s1">&#39;Hi!&#39;</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">cease</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">__active</span> <span class="o">=</span> <span class="bp">False</span>
        <span class="n">Golem</span><span class="o">.</span><span class="n">__population</span> <span class="o">-=</span> <span class="mi">1</span>

    <span class="k">def</span> <span class="nf">is_active</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">datetime</span><span class="o">.</span><span class="n">date</span><span class="o">.</span><span class="n">today</span><span class="p">()</span><span class="o">.</span><span class="n">year</span> <span class="o">-</span> <span class="bp">self</span><span class="o">.</span><span class="n">built_year</span> <span class="o">&gt;=</span> <span class="n">Golem</span><span class="o">.</span><span class="n">__life_span</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">cease</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">__active</span>

    <span class="nd">@property</span>
    <span class="k">def</span> <span class="nf">population</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">Golem</span><span class="o">.</span><span class="n">__population</span>

    <span class="nd">@population.setter</span>
    <span class="k">def</span> <span class="nf">population</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
        <span class="n">Golem</span><span class="o">.</span><span class="n">__population</span> <span class="o">=</span> <span class="n">value</span>

<span class="n">g</span> <span class="o">=</span> <span class="n">Golem</span><span class="p">(</span><span class="s1">&#39;Clay&#39;</span><span class="p">)</span>
<span class="n">g</span><span class="o">.</span><span class="n">population</span>
<span class="n">g</span><span class="o">.</span><span class="n">population</span> <span class="o">=</span> <span class="mi">100</span>
<span class="n">ga</span> <span class="o">=</span> <span class="n">Golem</span><span class="p">(</span><span class="s1">&#39;New&#39;</span><span class="p">)</span>
<span class="n">g</span><span class="o">.</span><span class="n">population</span>
<span class="n">ga</span><span class="o">.</span><span class="n">population</span>
<span class="n">help</span><span class="p">(</span><span class="n">Golem</span><span class="p">)</span>
<span class="n">Golem</span><span class="o">.</span><span class="vm">__dict__</span>
<span class="n">g</span><span class="o">.</span><span class="vm">__dict__</span>
<span class="nb">hasattr</span><span class="p">(</span><span class="n">Golem</span><span class="p">,</span> <span class="s1">&#39;population&#39;</span><span class="p">)</span>
<span class="nb">getattr</span><span class="p">(</span><span class="n">Golem</span><span class="p">,</span> <span class="s1">&#39;population&#39;</span><span class="p">)</span>
<span class="nb">setattr</span><span class="p">(</span><span class="n">Golem</span><span class="p">,</span> <span class="s1">&#39;population&#39;</span><span class="p">,</span> <span class="mi">10000</span><span class="p">)</span>
<span class="n">g</span><span class="o">.</span><span class="n">population</span>    <span class="c1"># 所以，在很多的情况下，不把数据封装在 Class 内部的话，后面会有很多麻烦。</span>
</pre></div>


<div class="highlight"><pre><span></span><span class="mi">1</span>
<span class="mi">101</span>
<span class="mi">101</span>
<span class="nx">Help</span> <span class="nx">on</span> <span class="kr">class</span> <span class="nx">Golem</span> <span class="k">in</span> <span class="kr">module</span> <span class="nx">__main__</span><span class="o">:</span>
<span class="kr">class</span> <span class="nx">Golem</span><span class="p">(</span><span class="nx">builtins</span><span class="p">.</span><span class="nx">object</span><span class="p">)</span>
 <span class="o">|</span>  <span class="nx">Golem</span><span class="p">(</span><span class="nx">name</span><span class="o">=</span><span class="nx">None</span><span class="p">)</span>
 <span class="o">|</span>
 <span class="o">|</span>  <span class="nx">Methods</span> <span class="nx">defined</span> <span class="nx">here</span><span class="o">:</span>
 <span class="o">|</span>
 <span class="o">|</span>  <span class="nx">__init__</span><span class="p">(</span><span class="nx">self</span><span class="p">,</span> <span class="nx">name</span><span class="o">=</span><span class="nx">None</span><span class="p">)</span>
 <span class="o">|</span>      <span class="nx">Initialize</span> <span class="nx">self</span><span class="p">.</span>  <span class="nx">See</span> <span class="nx">help</span><span class="p">(</span><span class="nx">type</span><span class="p">(</span><span class="nx">self</span><span class="p">))</span> <span class="k">for</span> <span class="nx">accurate</span> <span class="nx">signature</span><span class="p">.</span>
 <span class="o">|</span>
 <span class="o">|</span>  <span class="nx">cease</span><span class="p">(</span><span class="nx">self</span><span class="p">)</span>
 <span class="o">|</span>
 <span class="o">|</span>  <span class="nx">is_active</span><span class="p">(</span><span class="nx">self</span><span class="p">)</span>
 <span class="o">|</span>
 <span class="o">|</span>  <span class="nx">say_hi</span><span class="p">(</span><span class="nx">self</span><span class="p">)</span>
 <span class="o">|</span>
 <span class="o">|</span>  <span class="o">----------------------------------------------------------------------</span>
 <span class="o">|</span>  <span class="nx">Data</span> <span class="nx">descriptors</span> <span class="nx">defined</span> <span class="nx">here</span><span class="o">:</span>
 <span class="o">|</span>
 <span class="o">|</span>  <span class="nx">__dict__</span>
 <span class="o">|</span>      <span class="nx">dictionary</span> <span class="k">for</span> <span class="nx">instance</span> <span class="nx">variables</span> <span class="p">(</span><span class="k">if</span> <span class="nx">defined</span><span class="p">)</span>
 <span class="o">|</span>
 <span class="o">|</span>  <span class="nx">__weakref__</span>
 <span class="o">|</span>      <span class="nx">list</span> <span class="nx">of</span> <span class="nx">weak</span> <span class="nx">references</span> <span class="nx">to</span> <span class="nx">the</span> <span class="nx">object</span> <span class="p">(</span><span class="k">if</span> <span class="nx">defined</span><span class="p">)</span>
 <span class="o">|</span>
 <span class="o">|</span>  <span class="nx">population</span>
<span class="nx">mappingproxy</span><span class="p">({</span><span class="s1">&#39;__module__&#39;</span><span class="o">:</span> <span class="s1">&#39;__main__&#39;</span><span class="p">,</span>
              <span class="s1">&#39;_Golem__population&#39;</span><span class="o">:</span> <span class="mi">101</span><span class="p">,</span>
              <span class="s1">&#39;_Golem__life_span&#39;</span><span class="o">:</span> <span class="mi">10</span><span class="p">,</span>
              <span class="s1">&#39;__init__&#39;</span><span class="o">:</span> <span class="o">&lt;</span><span class="kd">function</span> <span class="nx">__main__</span><span class="p">.</span><span class="nx">Golem</span><span class="p">.</span><span class="nx">__init__</span><span class="p">(</span><span class="nx">self</span><span class="p">,</span> <span class="nx">name</span><span class="o">=</span><span class="nx">None</span><span class="p">)</span><span class="o">&gt;</span><span class="p">,</span>
              <span class="s1">&#39;say_hi&#39;</span><span class="o">:</span> <span class="o">&lt;</span><span class="kd">function</span> <span class="nx">__main__</span><span class="p">.</span><span class="nx">Golem</span><span class="p">.</span><span class="nx">say_hi</span><span class="p">(</span><span class="nx">self</span><span class="p">)</span><span class="o">&gt;</span><span class="p">,</span>
              <span class="s1">&#39;cease&#39;</span><span class="o">:</span> <span class="o">&lt;</span><span class="kd">function</span> <span class="nx">__main__</span><span class="p">.</span><span class="nx">Golem</span><span class="p">.</span><span class="nx">cease</span><span class="p">(</span><span class="nx">self</span><span class="p">)</span><span class="o">&gt;</span><span class="p">,</span>
              <span class="s1">&#39;is_active&#39;</span><span class="o">:</span> <span class="o">&lt;</span><span class="kd">function</span> <span class="nx">__main__</span><span class="p">.</span><span class="nx">Golem</span><span class="p">.</span><span class="nx">is_active</span><span class="p">(</span><span class="nx">self</span><span class="p">)</span><span class="o">&gt;</span><span class="p">,</span>
              <span class="s1">&#39;population&#39;</span><span class="o">:</span> <span class="o">&lt;</span><span class="nx">property</span> <span class="nx">at</span> <span class="mh">0x1068f9d68</span><span class="o">&gt;</span><span class="p">,</span>
              <span class="s1">&#39;__dict__&#39;</span><span class="o">:</span> <span class="o">&lt;</span><span class="nx">attribute</span> <span class="s1">&#39;__dict__&#39;</span> <span class="nx">of</span> <span class="s1">&#39;Golem&#39;</span> <span class="nx">objects</span><span class="o">&gt;</span><span class="p">,</span>
              <span class="s1">&#39;__weakref__&#39;</span><span class="o">:</span> <span class="o">&lt;</span><span class="nx">attribute</span> <span class="s1">&#39;__weakref__&#39;</span> <span class="nx">of</span> <span class="s1">&#39;Golem&#39;</span> <span class="nx">objects</span><span class="o">&gt;</span><span class="p">,</span>
              <span class="s1">&#39;__doc__&#39;</span><span class="o">:</span> <span class="nx">None</span><span class="p">})</span>
<span class="p">{</span><span class="s1">&#39;name&#39;</span><span class="o">:</span> <span class="s1">&#39;Clay&#39;</span><span class="p">,</span> <span class="s1">&#39;built_year&#39;</span><span class="o">:</span> <span class="mi">2019</span><span class="p">,</span> <span class="s1">&#39;_Golem__active&#39;</span><span class="o">:</span> <span class="nx">True</span><span class="p">}</span>
<span class="nx">True</span>
<span class="o">&lt;</span><span class="nx">property</span> <span class="nx">at</span> <span class="mh">0x1068f9d68</span><span class="o">&gt;</span>
<span class="mi">10000</span>
</pre></div>
    </div><!-- /.entry-content -->

  </article>
</section>
        <section id="extras" class="body">
                <div class="blogroll">
                        <h2>blogroll</h2>
                        <ul>
                            <li><a href="http://getpelican.com/">Pelican</a></li>
                            <li><a href="http://python.org/">Python.org</a></li>
                            <li><a href="http://jinja.pocoo.org/">Jinja2</a></li>
                            <li><a href="#">You can modify those links in your config file</a></li>
                        </ul>
                </div><!-- /.blogroll -->
                <div class="social">
                        <h2>social</h2>
                        <ul>

                            <li><a href="#">You can add links in your config file</a></li>
                            <li><a href="#">Another social link</a></li>
                        </ul>
                </div><!-- /.social -->
        </section><!-- /#extras -->

        <footer id="contentinfo" class="body">
                <p>Powered by <a href="http://www.maxiaoan.com/">Maxiaoan</a></p>
        </footer><!-- /#contentinfo -->

</body>
</html>